#!/usr/bin/env perl
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of the build configuration tools of the Qt Toolkit.
##
## $QT_BEGIN_LICENSE:LGPL$
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms
## and conditions see https://www.qt.io/terms-conditions. For further
## information use the contact form at https://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 3 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL3 included in the
## packaging of this file. Please review the following information to
## ensure the GNU Lesser General Public License version 3 requirements
## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
##
## GNU General Public License Usage
## Alternatively, this file may be used under the terms of the GNU
## General Public License version 2.0 or (at your option) the GNU General
## Public license version 3 or any later version approved by the KDE Free
## Qt Foundation. The licenses are as published by the Free Software
## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
## included in the packaging of this file. Please review the following
## information to ensure the GNU General Public License requirements will
## be met: https://www.gnu.org/licenses/gpl-2.0.html and
## https://www.gnu.org/licenses/gpl-3.0.html.
##
## $QT_END_LICENSE$
##
#############################################################################

# Reads list of headers in a file tree, from stdin, one per line, as
# paths relative to current working directory, in which sync.profile
# must be present.  Emits, to stdout, the same list of headers that
# syncqt.pl would treat as public, if in the given file tree - in the
# same format.
#
# Assumes the incoming file list has had some filtering applied to it;
# see api-review-gen's function apiheaders ().  To model a given git
# checkout, you need to check out its sync.profile and use git ls-tree
# -r --name-only to list its headers (via some filtering by grep);
# pipe that into this script.

# For such documentation as exists of sync.profile, see:
# https://wiki.qt.io/Creating_a_new_module_or_tool_for_Qt#The_sync.profile_script

use File::Basename 'basename';

######################################################################
# Syntax:  normalizePath(\$path)
# Params:  Reference to a path that's going to be normalized.
#
# Purpose: Converts the path into a form that can be used as include
#          path from C++ sources and qmake's .pro files.
#          No-op except on Windows.
# Returns: -none-
######################################################################
my $onMSys = $^O eq "msys";
sub normalizePath ($) {
    my $s = shift;
    $$s =~ s=\\=/=g;
    # Fix up drive letters on MSys:
    if ($onMSys && ($$s =~ m,^/([a-zA-Z])/(.*), || $$s =~ m,^([a-zA-Z]):/(.*),)) {
        $$s = lc($1) . ":/$2";
    }
}

sub cannot ($) {
    my $msg = shift;
    my $me = basename($0);
    die "$me couldn't $msg";
}

# Apt to be set by the module's sync.profile:
our (%modules, %moduleheaders, @allmoduleheadersprivate);
our @qpa_headers = (); # regexes matching Qt Platform Abstraction headers
our @ignore_headers = ();
our %inject_headers = ();
# TODO: add a variable by which modules can tell us where to find QML API

# Load the module's sync.profile:
my ($base, $sync) = ('.', 'sync.profile');
if (! -f $sync && -f "Source/$sync" ) {
    $base = 'Source';
    $sync = "$base/$sync";
}
if (-f $sync) {
    our (%classnames, %deprecatedheaders);
    our $basedir = $base; # Used by sync.profile
    unless (my $result = do "./$sync") {
        &cannot("parse $sync: $@") if $@;
        &cannot("execute $sync: $!") unless defined $result;
    }
} else {
    &cannot("find $sync");
}

# Short-cut for testing if entry is in list (our only use of these lists):
my %allmoduleheadersprivate = map { $_ => 1 } @allmoduleheadersprivate;
my %qpa_headers = map { $_ => 1 } @qpa_headers;
my %ignore_headers = map { $_ => 1 } @ignore_headers;
foreach my $dir (keys %inject_headers) {
    foreach $header ($inject_headers{$dir}) {
        $ignore_headers{"$dir/$header"} = 1;
    }
}

# Gather file-names listed (one per line) on STDIN, filtering out cruft:
my @allheaders = ();
while (<STDIN>) {
    chomp;
    normalizePath(\$_);
    next if $ignore_headers{$_} || $qpa_headers{$_};
    push @allheaders, $_ if $_;
}

foreach my $lib (keys %modules) {
    next if $allmoduleheadersprivate{$lib};
    # iteration info
    my $pathtoheaders = $moduleheaders{$lib} ? $moduleheaders{$lib} : "";
    my $module = $modules{$lib};
    my $is_qt = $module !~ s/^!//;
    my @dirs = split(/;/, $module);
    shift @dirs if $dirs[0] =~ s/^>//;

    foreach my $module_dir (@dirs) {
        next if $module_dir =~ /^\^/;
        my @headers_paths = split(/;/, $pathtoheaders);
        if (@headers_paths) {
            @headers_paths = map { "$module_dir/$_" } @headers_paths;
        } else {
            push @headers_paths, $module_dir;
        }

        foreach my $header_dir (@headers_paths) {
            $header_dir =~ s!/*$!/!;
            $header_dir =~ s!^\./+!!; # Strip $basedir prefix
            my @selected = grep /^\Q$header_dir\E/, @allheaders;
            print join("\n", @selected) . "\n" if @selected;
        }
    }
}
exit 0;
